Go 内嵌静态文件之 embed 包
embed 包是一个用来访问嵌入文件的包,先来说下为啥需要这个包
Golang 编译文件时并不会把配置文件之类的静态文件打包编译到二进制文件中,所以在 1.16 以前需要把静态资源打包成二进制文件需要使用第三方工具 go-bindata、statik、togo 等库,在 1.16 之后官方提供的这个 embed 包就是用来处理这事的
简单使用方式
例如当前项目目录上有个 config.yml 文件需要打包进来
import (
_ "embed"
)
//go:embed config.yml
var content string
func main() {
fmt.Println(content)
}
就能将这个 config.yml
文件的内容读取到这个 content 变量里面来了
Go 能够允许嵌入的变量类型有如下三种:
变量类型 | 说明 |
---|---|
[]byte | 用于存储二进制形式的数据,比如图片、富媒体等。 |
string | 用于存储 UTF-8 编码的字符串。 |
embed.FS | 用于嵌入多个文件和目录的结构。 |
go embed
仅能嵌入当前目录及其子目录,无法嵌入上层目录。同时也不支持软链接。go emebd 禁止嵌入如 .git .svn 这些目录,官方认为这些目录不属于 package 的一部分,如果嵌入则会在编译时报错。
嵌入多个文件:
import (
"embed"
)
//go:embed *.tmpl
var FS embed.FS
嵌入多个目录
.
├── css
│ └── sandbox.css
└── js
└── sandbox.js
import (
"embed"
)
//go:embed css js
var FS embed.FS
func main() {
fmt.Println(content)
}
然后读取这个 embed.FS 可以使用它提供的 ReadFile 方法
//go:embed config.yml
var FS embed.FS
func main() {
if bytes, err := FS.ReadFile("config.yml"); err != nil {
fmt.Println("Error reading config")
} else {
fmt.Println(string(bytes))
}
}
补充内容,读取 yml 文件的内容
host: localhost:3306
username: 'juan'
password: '123456'
使用 yaml 包解析 yml 文件
package main
import (
"embed"
"fmt"
"gopkg.in/yaml.v2"
)
//定义conf类型
//类型里的属性,全是配置文件里的属性
type conf struct {
Host string `yaml: "host"`
User string `yaml: "username"`
Pwd string `yaml: "password"`
}
//go:embed config.yml
var content embed.FS
func main() {
var c conf
bytes, err := content.ReadFile("config.yml")
if err != nil {
fmt.Println("Error reading config.yml")
}
yaml.Unmarshal(bytes, &c)
fmt.Printf("%v", c)
}
静态服务器
嵌入文件
// cli/embed.go
package cli
import (
"embed"
_ "embed"
)
var (
//go:embed assets
Staticfiles embed.FS
//go:embed index.html
IndexPage []byte
//go:embed vite.svg
Iconf []byte
)
Gin 加载
r := gin.Default()
fe, err := fs.Sub(cli.Staticfiles, "assets") // 多了一级目录
r.StaticFS("/assets", http.FS(fe))
r.GET("/", func(c *gin.Context) {
c.Header("content-type", "text/html;charset=utf-8")
c.String(200, string(cli.IndexPage))
})
s := &http.Server{
Addr: config.GlobalConfigVar.GetMWAddr(),
Handler: handlers.CORS(
handlers.AllowedMethods([]string{"GET", "POST", "PUT"}),
handlers.AllowedHeaders([]string{"Accept", "Accept-Language", "Content-Type", "Content-Language", "Origin"}),
handlers.AllowedOrigins([]string{"*"}),
)(r),
}
注意!!! 这里多了一级目录